WinForms Interop, Drag & Drop from WinForms -> WPF?

Pedery & jmayor: Thanks for the suggestions guys! (see my findings below).

Pedery & jmayor: Thanks for the suggestions guys! (see my findings below) After quite a few experimentation, trials and errors, and a bit of "Reflector'ing", I managed to figure out exactly why I was receiving the cryptic error message "Error HRESULT E_FAIL has been returned from a call to a COM component". It was due to the fact that when dragging data WPF Winforms in a same app, that data has to be Serializable!

I've checked how difficult it would be to transform all of our classes to "Serializable" and I would have a been a real pain for a couple of reasons... one, we would need to practically make all of classes serializable and two, some of these classes have references to Controls! And Controls aren't serializable. So a major refactoring would have been needed.So... since we wanted to pass any object of any class to drag from/to WPF inside the same application, I decided to create a wrapper class, with the Serializable attribute and implementing ISerializable.

I would have 1 contructor with 1 parameter of type "object" which would be the actual drag data. That wrapper, when serializing/de-serializing, would serialize not the object itself... but rather the IntPtr to the object (which we can do since we only want that functionnality inside our 1 instance only application. ) See code sample below: Serializable public class DataContainer : ISerializable { public object Data { get; set; } public DataContainer(object data) { Data = data; } // Deserialization constructor protected DataContainer(SerializationInfo info, StreamingContext context) { IntPtr address = (IntPtr)info.

GetValue("dataAddress", typeof(IntPtr)); GCHandle handle = GCHandle. FromIntPtr(address); Data = handle. Target; handle.Free(); } #region ISerializable Members public void GetObjectData(SerializationInfo info, StreamingContext context) { GCHandle handle = GCHandle.

Alloc(Data); IntPtr address = GCHandle. ToIntPtr(handle); info. AddValue("dataAddress", address); } #endregion } To keep the IDataObject functionnality, I created the following DataObject wrapper: public class DataObject : IDataObject { System.Collections.

Hashtable _Data = new System.Collections.Hashtable(); public DataObject() { } public DataObject(object data) { SetData(data); } public DataObject(string format, object data) { SetData(format, data); } #region IDataObject Members public object GetData(Type format) { return _Dataformat. FullName; } public bool GetDataPresent(Type format) { return _Data. ContainsKey(format.

FullName); } public string GetFormats() { string strArray = new string_Data.Keys. Count; _Data.Keys. CopyTo(strArray, 0); return strArray; } public string GetFormats(bool autoConvert) { return GetFormats(); } private void SetData(object data, string format) { object obj = new DataContainer(data); if (string.

IsNullOrEmpty(format)) { // Create a dummy DataObject object to retrieve all possible formats. // Ex. : For a System.

String type, GetFormats returns 3 formats: // "System. String", "UnicodeText" and "Text" System.Windows.Forms. DataObject dataObject = new System.Windows.Forms.

DataObject(data); foreach (string fmt in dataObject.GetFormats()) { _Datafmt = obj; } } else { _Dataformat = obj; } } public void SetData(object data) { SetData(data, null); } #endregion } And we are using the above classes like this: myControl. DoDragDrop(new MyNamespace. DataObject(myNonSerializableObject)); // in the drop event for example e.Data.

GetData(typeof(myNonSerializableClass)); I know I know... it's not very pretty... but it's doing what we wanted. We also created a dragdrop helper class which masks the DataObject creation and has templated GetData functions to retrieve the data without any cast... a bit like: myNonSerializableClass newObj = DragDropHelper. GetData(e.

Data); So thanks again for the replies! You guys gave me good ideas where to look at for possible solutions! -Oli.

I had a "similar" issue some time ago so I can at least tell you what I found out. It seems . Net is resorting to OLE remoting when drag/drop operations are performed in not the simplest of cases.

For some reason GetDataPresent will in these cases be successful and GetData will fail. This is furthermore mystified by the fact that there are several versions of the IDataObject in the . Net framework.

Windows Forms defaults to System.Windows.Forms.IDataObject. However, in your case you could try to give System.Runtime.InteropServices.ComTypes. IDataObject a shot instead.

You can also check out my discussion here. Hope this helps.

Seems wonderfull at first sight. I tried it but got some errors on implementations. I began to correct some errors when I decided to look for something a little bit more simplier, that do not have pointers (humm I don't like that, particularly with carbage collection, but I have no idea if it could have real impact) and that do not use Interop.

I come up with that. It works for me and I hope it will work for anybody else. It is only intended to be used for local drag drop (inside the same app).

How to use to drag: DragDrop. DoDragDrop(listBoxOfAvailableScopes, new DragDropLocal(GetSelectedSimulResultScopes()), DragDropEffects. Copy); How to use to drop (get): DragDropLocal dragDropLocal = (DragDropLocal)e.Data.

GetData(typeof(DragDropLocal)); SimulResultScopes simulResultScopes = (SimulResultScopes)dragDropLocal.GetObject(); Code: namespace Util { Serializable public class DragDropLocal { private static readonly Dictionary _dictOfDragDropLocalKeyToDragDropSource = new Dictionary(); private Guid _guid = Guid.NewGuid(); public DragDropLocal(object objToDrag) { _dictOfDragDropLocalKeyToDragDropSource. Add(_guid, objToDrag); } public object GetObject() { object obj; _dictOfDragDropLocalKeyToDragDropSource. TryGetValue(_guid, out obj); return obj; } ~DragDropLocal() { _dictOfDragDropLocalKeyToDragDropSource.

Remove(_guid); } } }.

Maybe the events are in the opposite way. The PreviewDragEnter should be related with the WPFTextBox. Also watch out the DragEventArgs class.

There is one in System.Windows. Form ( Windows Form version) and the one under System. Windows( for WPF version).

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions